package com.tcxhb.job.core.schedule.workflow;

import com.tcxhb.job.dao.dataobject.JobInstanceDO;
import com.tcxhb.job.common.constants.CommonErrorCode;
import com.tcxhb.job.common.constants.enums.ExecuteStatus;
import com.tcxhb.job.common.constants.enums.ScheduleStatus;
import com.tcxhb.job.common.model.MiscResult;
import com.tcxhb.job.core.constants.enums.LogActionEnum;
import com.tcxhb.job.core.schedule.execute.JobRunContext;
import com.tcxhb.job.core.schedule.handler.HandlerFactory;
import com.tcxhb.job.core.schedule.handler.JobHandler;
import com.tcxhb.job.core.service.job.JobInstanceService;
import com.tcxhb.job.core.utils.LogUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * @Description:
 * @Auther: tcxhb
 * @Date: 2023/11/12
 */
@Component
@Slf4j
public class InstanceRunFlow implements FlowHandler<JobRunContext> {
    @Autowired
    private HandlerFactory factory;
    @Autowired
    private JobInstanceService instanceService;

    @Override
    public MiscResult handle(JobRunContext context) {
        for (JobInstanceDO instanceDO : context.getInstanceList()) {
            MiscResult<Boolean> result = dispatchToAgent(instanceDO);
            updateInstance(instanceDO, result);
        }
        return MiscResult.suc();
    }

    /**
     * 提交到端上执行
     *
     * @param instanceDO
     */
    public MiscResult<Boolean> dispatchToAgent(JobInstanceDO instanceDO) {
        if (StringUtils.isBlank(instanceDO.getMachineAddr())) {
            log.error("no machine:{}", instanceDO.getAppName());
            return MiscResult.err(CommonErrorCode.MACHINE_NOT_FOUND);
        }
        //执行接口
        JobHandler handler = factory.getBean(instanceDO.getJobParams().getType());
        MiscResult<Boolean> result = handler.handle(instanceDO);
        //转发到客户端
        LogUtils.info(instanceDO.getTraceId(), LogActionEnum.RouteAgent, instanceDO.getMachineAddr() + "," + result.getCode());
        return result;
    }

    /**
     * 更新数据库
     *
     * @param instanceDO
     * @param result
     */
    public void updateInstance(JobInstanceDO instanceDO, MiscResult result) {
        // 调度成功, 提交成功
        JobInstanceDO updateDO = new JobInstanceDO();
        updateDO.setId(instanceDO.getId());
        updateDO.setMachineAddr(instanceDO.getMachineAddr());
        // 默认都允许重试,判断下次是否允许重试
        if (instanceDO.getFailCount() >= instanceDO.getRunStrategy().getRetryCount()) {
            updateDO.setRetryFlag(0);
        }
        //不管成功还是失败都 + 1
        updateDO.setFailCount(instanceDO.getFailCount() + 1);
        if (!result.isSuccess()) {
            //提交失败
            updateDO.setScheduleStatus(ScheduleStatus.FAIL.getType());
            updateDO.setMsg(result.getMsg());
        } else {
            //调度成功
            updateDO.setScheduleStatus(ScheduleStatus.SUCC.getType());
            updateDO.setExecuteStatus(ExecuteStatus.WAIT_CPU.getType());
            updateDO.setExecuteTime(new Date());
            updateDO.setMsg("schedule-succ");
        }
        Boolean succ = instanceService.updateById(updateDO);
        //更新状态
        LogUtils.info(instanceDO.getTraceId(), LogActionEnum.UpdateScheduleStatus, updateDO.getScheduleStatus() + "," + succ);
    }
}
